package com.ruoyi.common.utils;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

import static javax.crypto.Cipher.SECRET_KEY;


/**
 * 对称式加密算法
 */
public class AESUtil {

    private static Logger logger = LogManager.getLogger(AESUtil.class);

    /**
     * 加密
     * @param sSrc  加密内容
     * @param sKey  密钥
     * @return
     * @throws Exception
     */
    public static String Encrypt(String sSrc, String sKey) throws Exception {
        byte[] raw = sKey.getBytes("utf-8");
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//"算法/模式/补码方式"
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
        byte[] encrypted = cipher.doFinal(sSrc.getBytes("utf-8"));
        return parseByte2HexStr(encrypted);
        //return new Base64().encodeToString(encrypted);//此处使用BASE64做转码功能，同时能起到2次加密的作用。
    }

    // 加密
    public static String EncryptBase64(String sSrc, String sKey) throws Exception {
        byte[] raw = sKey.getBytes("utf-8");
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//"算法/模式/补码方式"
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
        byte[] encrypted = cipher.doFinal(sSrc.getBytes("utf-8"));
        return Base64.getEncoder().encodeToString(encrypted);//此处使用BASE64做转码功能，同时能起到2次加密的作用。
    }

    /**
     * 解密
     * @param sSrc 秘文
     * @param sKey 密钥
     * @return
     */
    public static  String Decrypt(String sSrc, String sKey) {
        try {
            byte[] raw = sKey.getBytes("utf-8");
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, skeySpec);
            // byte[] encrypted1 = new Base64().decode(sSrc);//先用base64解密

            try {
                // byte[] original = cipher.doFinal(encrypted1);
                byte[] original = cipher.doFinal(parseHexStr2Byte(sSrc));
                String originalString = new String(original,"utf-8");
                return originalString;
            } catch (Exception e) {
                logger.error("AES解密失败：" + e.getMessage(),e);
                return null;
            }
        } catch (Exception ex) {
            logger.error("AES解密失败：" + ex.getMessage(),ex);
            return null;
        }
    }
    public static String encryptCbc(String data,String SECRET_KEY) {
        try {
            SecretKeySpec secretKeySpec = new SecretKeySpec(SECRET_KEY.getBytes(StandardCharsets.UTF_8), "AES");
            IvParameterSpec ivParameterSpec = new IvParameterSpec(SECRET_KEY.getBytes(StandardCharsets.UTF_8));

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);

            byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(encrypted);
        } catch (Exception e) {
            throw new RuntimeException();
        }
    }
    // 解密
    public static String DecryptBase64(String sSrc, String sKey) throws Exception {
        try {
            byte[] raw = sKey.getBytes("utf-8");
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, skeySpec);
            byte[] encrypted1 = Base64.getDecoder().decode(sSrc);//先用base64解密

            try {
                byte[] original = cipher.doFinal(encrypted1);
                //byte[] original = cipher.doFinal(parseHexStr2Byte(sSrc));
                String originalString = new String(original,"utf-8");
                return originalString;
            } catch (Exception e) {
                logger.error("AES解密失败：" + e.getMessage(),e);
                return null;
            }
        } catch (Exception ex) {
            logger.error("AES解密失败：" + ex.getMessage(),ex);
            return null;
        }
    }

    //将二进制转换为16进制
    public static String parseByte2HexStr(byte[] buf) {
        StringBuffer sb = new StringBuffer();
        for(int i=0;i<buf.length;i++) {
            String hex = 	Integer.toHexString(buf[i] & 0xFF);
            if(hex.length() == 1) {
                hex='0'+hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    //将16进制转换为二进制
    public static byte[] parseHexStr2Byte(String hexStr) {
        if(hexStr.length()<1) {
            return null;
        }
        byte[] result = new byte[hexStr.length()/2];
        for(int i=0;i<hexStr.length()/2;i++) {
            int high = Integer.parseInt(hexStr.substring(i*2, i*2+1),16);
            int low = Integer.parseInt(hexStr.substring(i*2+1,i*2+2),16);
            result[i] = (byte)(high*16+low);
        }
        return result;
    }


    /**
     * 加密
     * @param sSrc 原文
     * @return
     * @throws Exception
     */
//    public static String Encrypt(String sSrc) throws Exception {
//        return Encrypt(sSrc, Config.AESSECRET);
//    }

    /**
     * 解密
     * @param sSrc 秘文
     * @return
     */
//    public static  String Decrypt(String sSrc) {
//        return Decrypt(sSrc, Config.AESSECRET);
//    }

    public static void main(String args[])  throws Exception {

        String sSrc = "1435421648164167681@17356523872@2022-04-29 14:52:00";
        String Encrypt = AESUtil.Encrypt(sSrc,"1234567891234567");
        System.out.println("加密后"+  Encrypt);
        String Decrypt = AESUtil.Decrypt(Encrypt,"1234567891234567");
        System.out.println("解密后"+Decrypt);
    }


}

